<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebGL 3D动画工具 - 完整关键帧系统</title>
    <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/controls/OrbitControls.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        body {
            display: flex;
            flex-direction: column;
            height: 100vh;
            background: #1e1e1e;
            color: #e0e0e0;
            overflow: hidden;
        }
        
        header {
            padding: 15px;
            background: #252526;
            border-bottom: 1px solid #3e3e42;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        
        .logo {
            font-size: 22px;
            font-weight: bold;
            color: #569cd6;
        }
        
        .main-container {
            display: flex;
            flex: 1;
            overflow: hidden;
        }
        
        .left-panel {
            display: flex;
            flex-direction: column;
            width: 300px;
        }
        
        .tool-panel {
            background: #252526;
            padding: 15px;
            border-right: 1px solid #3e3e42;
            overflow-y: auto;
        }
        
        .tool-section {
            margin-bottom: 20px;
        }
        
        .tool-section h3 {
            margin-bottom: 10px;
            color: #9cdcfe;
            font-size: 16px;
        }
        
        .tool-btn {
            display: block;
            width: 100%;
            padding: 8px 12px;
            margin: 5px 0;
            background: #2d2d30;
            border: 1px solid #3e3e42;
            color: #d4d4d4;
            border-radius: 4px;
            cursor: pointer;
            text-align: left;
            transition: all 0.2s;
        }
        
        .tool-btn:hover {
            background: #37373d;
        }
        
        .tool-btn.active {
            background: #094771;
            border-color: #007acc;
        }
        
        .objects-panel {
            flex: 1;
            background: #252526;
            border-right: 1px solid #3e3e42;
            border-top: 1px solid #3e3e42;
            overflow-y: auto;
            padding: 15px;
        }
        
        .objects-list {
            list-style: none;
        }
        
        .object-item {
            padding: 8px 12px;
            margin: 5px 0;
            background: #2d2d30;
            border: 1px solid #3e3e42;
            border-radius: 4px;
            cursor: pointer;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        
        .object-item:hover {
            background: #37373d;
        }
        
        .object-item.selected {
            background: #094771;
            border-color: #007acc;
        }
        
        .object-visibility {
            cursor: pointer;
            padding: 2px 5px;
            border-radius: 3px;
        }
        
        .render-container {
            flex: 1;
            position: relative;
            overflow: hidden;
        }
        
        #renderCanvas {
            width: 100%;
            height: 100%;
            display: block;
        }
        
        .mode-indicator {
            position: absolute;
            top: 15px;
            right: 15px;
            padding: 5px 10px;
            background: #007acc;
            border-radius: 3px;
            font-size: 14px;
        }
        
        .properties-panel {
            width: 300px;
            background: #252526;
            padding: 15px;
            border-left: 1px solid #3e3e42;
            overflow-y: auto;
            display: flex;
            flex-direction: column;
        }
        
        .property-tabs {
            display: flex;
            margin-bottom: 15px;
            border-bottom: 1px solid #3e3e42;
        }
        
        .property-tab {
            padding: 8px 15px;
            cursor: pointer;
            background: #2d2d30;
            margin-right: 5px;
            border-top-left-radius: 4px;
            border-top-right-radius: 4px;
        }
        
        .property-tab.active {
            background: #007acc;
        }
        
        .property-group {
            margin-bottom: 15px;
        }
        
        .property-group h3 {
            margin-bottom: 10px;
            color: #9cdcfe;
            font-size: 16px;
        }
        
        .property {
            margin-bottom: 10px;
        }
        
        .property label {
            display: block;
            margin-bottom: 5px;
            color: #ce9178;
        }
        
        .property input, .property select {
            width: 100%;
            padding: 5px;
            background: #3c3c3c;
            border: 1px solid #3e3e42;
            color: #d4d4d4;
            border-radius: 3px;
        }
        
        .color-input {
            display: flex;
            align-items: center;
        }
        
        .color-input input[type="color"] {
            margin-left: 10px;
            width: 40px;
            height: 30px;
            border: none;
        }
        
        .timeline {
            height: 220px;
            background: #252526;
            border-top: 1px solid #3e3e42;
            padding: 15px;
            overflow-x: auto;
            display: flex;
            flex-direction: column;
        }
        
        .timeline-controls {
            display: flex;
            margin-bottom: 10px;
            align-items: center;
        }
        
        .timeline-btn {
            padding: 6px 12px;
            margin-right: 8px;
            background: #2d2d30;
            border: 1px solid #3e3e42;
            color: #d4d4d4;
            border-radius: 4px;
            cursor: pointer;
        }
        
        .timeline-btn.active {
            background: #094771;
            border-color: #007acc;
        }
        
        .timeline-track-container {
            flex: 1;
            position: relative;
            overflow: hidden;
        }
        
        .timeline-ruler {
            height: 20px;
            background: #2d2d30;
            border-radius: 4px 4px 0 0;
            position: relative;
            border-bottom: 1px solid #3e3e42;
        }
        
        .ruler-mark {
            position: absolute;
            bottom: 0;
            width: 1px;
            height: 6px;
            background: #666;
        }
        
        .ruler-label {
            position: absolute;
            bottom: -18px;
            font-size: 10px;
            transform: translateX(-50%);
            color: #999;
        }
        
        .timeline-track {
            height: 80px;
            background: #2d2d30;
            border-radius: 0 0 4px 4px;
            position: relative;
        }
        
        .playhead {
            position: absolute;
            top: 0;
            width: 2px;
            height: 100%;
            background: #f00;
            z-index: 10;
            left: 0;
        }
        
        .keyframe {
            position: absolute;
            width: 14px;
            height: 14px;
            background: #ffa500;
            border-radius: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
            z-index: 5;
            cursor: pointer;
            border: 2px solid #000;
        }
        
        .keyframe.selected {
            background: #ff0000;
            border: 2px solid #fff;
        }
        
        .keyframe-line {
            position: absolute;
            height: 2px;
            background: #569cd6;
            top: 50%;
            transform: translateY(-50%);
            z-index: 2;
        }
        
        .animation-curve {
            position: absolute;
            bottom: 0;
            left: 0;
            width: 100%;
            height: 30px;
            background: rgba(86, 156, 214, 0.1);
            border-top: 1px solid #3e3e42;
        }
        
        .curve-point {
            position: absolute;
            width: 6px;
            height: 6px;
            background: #9cdcfe;
            border-radius: 50%;
            transform: translate(-50%, -50%);
            cursor: pointer;
        }
        
        .modal {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.7);
            z-index: 100;
            justify-content: center;
            align-items: center;
        }
        
        .modal-content {
            background: #252526;
            padding: 20px;
            border-radius: 8px;
            width: 400px;
            max-width: 90%;
        }
        
        .modal h2 {
            margin-bottom: 15px;
            color: #569cd6;
        }
        
        .export-options {
            display: flex;
            flex-direction: column;
        }
        
        .export-option {
            margin: 8px 0;
            padding: 10px;
            background: #2d2d30;
            border: 1px solid #3e3e42;
            color: #d4d4d4;
            border-radius: 4px;
            cursor: pointer;
            text-align: left;
        }
        
        .export-option:hover {
            background: #37373d;
        }
        
        .close-modal {
            margin-top: 15px;
            padding: 8px 15px;
            background: #0e639c;
            border: none;
            color: white;
            border-radius: 4px;
            cursor: pointer;
            float: right;
        }
        
        .easing-selector {
            display: flex;
            flex-wrap: wrap;
            gap: 5px;
            margin-top: 10px;
        }
        
        .easing-btn {
            padding: 5px 10px;
            background: #2d2d30;
            border: 1px solid #3e3e42;
            color: #d4d4d4;
            border-radius: 3px;
            cursor: pointer;
            font-size: 12px;
        }
        
        .easing-btn.active {
            background: #094771;
            border-color: #007acc;
        }
    </style>
</head>
<body>
    <header>
        <div class="logo">WebGL 3D动画工具 - 完整关键帧系统</div>
        <div>
            <button class="timeline-btn" id="previewBtn">预览模式</button>
            <button class="timeline-btn" id="exportBtn">导出项目</button>
            <button class="timeline-btn" id="helpBtn">帮助</button>
        </div>
    </header>
    
    <div class="main-container">
        <div class="left-panel">
            <div class="tool-panel">
                <div class="tool-section">
                    <h3>创建模型</h3>
                    <button class="tool-btn" id="addCube">立方体</button>
                    <button class="tool-btn" id="addSphere">球体</button>
                    <button class="tool-btn" id="addCone">圆锥体</button>
                    <button class="tool-btn" id="addCylinder">圆柱体</button>
                    <button class="tool-btn" id="addPlane">平面</button>
                </div>
                
                <div class="tool-section">
                    <h3>编辑工具</h3>
                    <button class="tool-btn active" id="selectTool">选择工具</button>
                    <button class="tool-btn" id="moveTool">移动工具</button>
                    <button class="tool-btn" id="rotateTool">旋转工具</button>
                    <button class="tool-btn" id="scaleTool">缩放工具</button>
                </div>
                
                <div class="tool-section">
                    <h3>场景</h3>
                    <button class="tool-btn" id="addLight">添加光源</button>
                    <button class="tool-btn" id="changeBg">更改背景</button>
                    <button class="tool-btn" id="addCamera">添加相机</button>
                </div>
            </div>
            
            <div class="objects-panel">
                <h3>对象列表</h3>
                <ul class="objects-list" id="objectsList">
                    <!-- 对象将通过JS动态添加 -->
                </ul>
            </div>
        </div>
        
        <div class="render-container">
            <canvas id="renderCanvas"></canvas>
            <div class="mode-indicator" id="modeIndicator">编辑模式</div>
        </div>
        
        <div class="properties-panel">
            <div class="property-tabs">
                <div class="property-tab active" data-tab="transform">变换</div>
                <div class="property-tab" data-tab="material">材质</div>
                <div class="property-tab" data-tab="animation">动画</div>
            </div>
            
            <div class="property-content" id="transformTab">
                <div class="property-group">
                    <h3>位置</h3>
                    <div class="property">
                        <label>X</label>
                        <input type="number" id="positionX" value="0" step="0.1">
                    </div>
                    <div class="property">
                        <label>Y</label>
                        <input type="number" id="positionY" value="0" step="0.1">
                    </div>
                    <div class="property">
                        <label>Z</label>
                        <input type="number" id="positionZ" value="0" step="0.1">
                    </div>
                </div>
                
                <div class="property-group">
                    <h3>旋转</h3>
                    <div class="property">
                        <label>X</label>
                        <input type="number" id="rotationX" value="0" step="1">
                    </div>
                    <div class="property">
                        <label>Y</label>
                        <input type="number" id="rotationY" value="0" step="1">
                    </div>
                    <div class="property">
                        <label>Z</label>
                        <input type="number" id="rotationZ" value="0" step="1">
                    </div>
                </div>
                
                <div class="property-group">
                    <h3>缩放</h3>
                    <div class="property">
                        <label>X</label>
                        <input type="number" id="scaleX" value="1" step="0.1">
                    </div>
                    <div class="property">
                        <label>Y</label>
                        <input type="number" id="scaleY" value="1" step="0.1">
                    </div>
                    <div class="property">
                        <label>Z</label>
                        <input type="number" id="scaleZ" value="1" step="0.1">
                    </div>
                </div>
            </div>
            
            <div class="property-content" id="materialTab" style="display: none;">
                <div class="property-group">
                    <h3>材质属性</h3>
                    <div class="property">
                        <label>颜色</label>
                        <div class="color-input">
                            <input type="text" id="materialColor" value="#ff6b6b">
                            <input type="color" id="materialColorPicker" value="#ff6b6b">
                        </div>
                    </div>
                    <div class="property">
                        <label>金属度</label>
                        <input type="range" id="metalness" min="0" max="1" step="0.1" value="0.5">
                    </div>
                    <div class="property">
                        <label>粗糙度</label>
                        <input type="range" id="roughness" min="0" max="1" step="0.1" value="0.5">
                    </div>
                    <div class="property">
                        <label>透明度</label>
                        <input type="range" id="opacity" min="0" max="1" step="0.1" value="1">
                    </div>
                </div>
            </div>
            
            <div class="property-content" id="animationTab" style="display: none;">
                <div class="property-group">
                    <h3>关键帧</h3>
                    <button class="tool-btn" id="addKeyframe">添加关键帧</button>
                    <button class="tool-btn" id="removeKeyframe">删除关键帧</button>
                    <button class="tool-btn" id="copyKeyframe">复制关键帧</button>
                    <div class="property">
                        <label>当前时间</label>
                        <input type="number" id="currentTimeInput" value="0" step="0.1" min="0">
                    </div>
                </div>
                
                <div class="property-group">
                    <h3>动画设置</h3>
                    <div class="property">
                        <label>动画时长 (秒)</label>
                        <input type="number" id="animationDuration" value="10" min="1" max="60">
                    </div>
                    <div class="property">
                        <label>循环动画</label>
                        <select id="animationLoop">
                            <option value="true">是</option>
                            <option value="false">否</option>
                        </select>
                    </div>
                    <div class="property">
                        <label>插值方式</label>
                        <select id="interpolationType">
                            <option value="linear">线性</option>
                            <option value="easeIn">缓入</option>
                            <option value="easeOut">缓出</option>
                            <option value="easeInOut">缓入缓出</option>
                        </select>
                    </div>
                </div>
                
                <div class="property-group">
                    <h3>关键帧属性</h3>
                    <div id="keyframeProperties">
                        <p>选择关键帧以编辑属性</p>
                    </div>
                </div>
            </div>
        </div>
    </div>
    
    <div class="timeline">
        <div class="timeline-controls">
            <button class="timeline-btn" id="playBtn">▶️ 播放</button>
            <button class="timeline-btn" id="pauseBtn">⏸️ 暂停</button>
            <button class="timeline-btn" id="stopBtn">⏹️ 停止</button>
            <button class="timeline-btn" id="prevKeyframe">⏮️ 上一个</button>
            <button class="timeline-btn" id="nextKeyframe">⏭️ 下一个</button>
            <input type="range" id="timelineSlider" min="0" max="100" value="0" style="width: 300px; margin: 0 15px;">
            <span id="timeIndicator">0.0s / 10.0s</span>
        </div>
        
        <div class="timeline-track-container">
            <div class="timeline-ruler" id="timelineRuler">
                <!-- 时间刻度将通过JS动态添加 -->
            </div>
            <div class="timeline-track" id="timelineTrack">
                <div class="playhead" id="playhead"></div>
                <!-- 关键帧和动画曲线将通过JS动态添加 -->
            </div>
            <div class="animation-curve" id="animationCurve">
                <!-- 动画曲线将通过JS动态添加 -->
            </div>
        </div>
    </div>
    
    <div class="modal" id="exportModal">
        <div class="modal-content">
            <h2>导出选项</h2>
            <div class="export-options">
                <button class="export-option">导出为GLTF格式</button>
                <button class="export-option">导出为OBJ格式</button>
                <button class="export-option">导出动画序列</button>
                <button class="export-option">导出为Three.js代码</button>
            </div>
            <button class="close-modal" id="closeExportModal">关闭</button>
        </div>
    </div>
    
    <div class="modal" id="backgroundModal">
        <div class="modal-content">
            <h2>背景设置</h2>
            <div class="property">
                <label>背景颜色</label>
                <div class="color-input">
                    <input type="text" id="backgroundColor" value="#2c2c2c">
                    <input type="color" id="backgroundColorPicker" value="#2c2c2c">
                </div>
            </div>
            <div class="property">
                <label>环境贴图</label>
                <select id="environmentMap">
                    <option value="none">无</option>
                    <option value="sky">天空</option>
                    <option value="city">城市</option>
                    <option value="studio">工作室</option>
                </select>
            </div>
            <div class="property">
                <label>背景透明度</label>
                <input type="range" id="backgroundAlpha" min="0" max="1" step="0.1" value="1">
            </div>
            <button class="close-modal" id="closeBackgroundModal">应用</button>
        </div>
    </div>

    <script>
        // Three.js场景初始化
        let scene, camera, renderer, controls;
        let objects = [];
        let cameras = [];
        let selectedObject = null;
        let clock = new THREE.Clock();
        let isPlaying = false;
        let isPreviewMode = false;
        let currentTime = 0;
        let animationDuration = 10; // 10秒动画
        let keyframes = [];
        let selectedKeyframe = null;
        let interpolationType = 'linear';

        // 初始化场景
        function init() {
            // 创建场景
            scene = new THREE.Scene();
            scene.background = new THREE.Color(0x2c2c2c);
            
            // 创建主相机
            camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.name = "主相机";
            camera.position.z = 5;
            cameras.push(camera);
            
            // 创建渲染器
            renderer = new THREE.WebGLRenderer({ 
                canvas: document.getElementById('renderCanvas'),
                antialias: true 
            });
            renderer.setSize(document.querySelector('.render-container').offsetWidth, 
                             document.querySelector('.render-container').offsetHeight);
            renderer.shadowMap.enabled = true;
            
            // 添加轨道控制
            controls = new THREE.OrbitControls(camera, renderer.domElement);
            controls.enableDamping = true;
            
            // 添加环境光
            const ambientLight = new THREE.AmbientLight(0x404040);
            ambientLight.name = "环境光";
            scene.add(ambientLight);
            objects.push(ambientLight);
            
            // 添加定向光
            const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
            directionalLight.name = "定向光";
            directionalLight.position.set(1, 1, 1);
            directionalLight.castShadow = true;
            scene.add(directionalLight);
            objects.push(directionalLight);
            
            // 添加网格地面
            const gridHelper = new THREE.GridHelper(20, 20, 0x444444, 0x222222);
            gridHelper.name = "网格辅助";
            scene.add(gridHelper);
            objects.push(gridHelper);
            
            // 添加坐标轴辅助
            const axesHelper = new THREE.AxesHelper(3);
            axesHelper.name = "坐标轴辅助";
            scene.add(axesHelper);
            objects.push(axesHelper);
            
            // 更新对象列表
            updateObjectsList();
            
            // 初始化时间轴
            initTimeline();
            
            // 窗口大小调整事件
            window.addEventListener('resize', onWindowResize);
            
            // 启动动画循环
            animate();
        }
        
        // 初始化时间轴
        function initTimeline() {
            const ruler = document.getElementById('timelineRuler');
            ruler.innerHTML = '';
            
            // 添加时间刻度
            for (let i = 0; i <= animationDuration; i++) {
                const mark = document.createElement('div');
                mark.className = 'ruler-mark';
                mark.style.left = (i / animationDuration * 100) + '%';
                
                const label = document.createElement('div');
                label.className = 'ruler-label';
                label.textContent = i + 's';
                label.style.left = (i / animationDuration * 100) + '%';
                
                ruler.appendChild(mark);
                ruler.appendChild(label);
            }
        }
        
        // 窗口大小调整
        function onWindowResize() {
            camera.aspect = document.querySelector('.render-container').offsetWidth / 
                            document.querySelector('.render-container').offsetHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(document.querySelector('.render-container').offsetWidth, 
                             document.querySelector('.render-container').offsetHeight);
        }
        
        // 动画循环
        function animate() {
            requestAnimationFrame(animate);
            
            const delta = clock.getDelta();
            
            if (isPlaying) {
                currentTime += delta;
                if (currentTime > animationDuration) {
                    if (document.getElementById('animationLoop').value === 'true') {
                        currentTime = 0;
                    } else {
                        currentTime = animationDuration;
                        isPlaying = false;
                    }
                }
                
                updatePlayhead();
                updateAnimations();
            }
            
            controls.update();
            renderer.render(scene, camera);
        }
        
        // 更新播放头位置
        function updatePlayhead() {
            const percent = (currentTime / animationDuration) * 100;
            document.getElementById('playhead').style.left = percent + '%';
            document.getElementById('timeIndicator').textContent = currentTime.toFixed(1) + 's / ' + animationDuration.toFixed(1) + 's';
            document.getElementById('timelineSlider').value = percent;
            document.getElementById('currentTimeInput').value = currentTime.toFixed(1);
        }
        
        // 更新动画
        function updateAnimations() {
            if (!selectedObject || keyframes.length < 2) return;
            
            // 找到当前时间所在的关键帧区间
            let prevKeyframe = null;
            let nextKeyframe = null;
            
            for (let i = 0; i < keyframes.length; i++) {
                if (keyframes[i].time <= currentTime) {
                    prevKeyframe = keyframes[i];
                } else {
                    nextKeyframe = keyframes[i];
                    break;
                }
            }
            
            // 如果不在任何区间内，直接返回
            if (!prevKeyframe || !nextKeyframe) return;
            
            // 计算时间比例 (0到1之间)
            const t = (currentTime - prevKeyframe.time) / (nextKeyframe.time - prevKeyframe.time);
            
            // 应用插值函数
            let easedT = t;
            switch (interpolationType) {
                case 'easeIn':
                    easedT = easeIn(t);
                    break;
                case 'easeOut':
                    easedT = easeOut(t);
                    break;
                case 'easeInOut':
                    easedT = easeInOut(t);
                    break;
                default:
                    // 线性插值，不需要修改
                    break;
            }
            
            // 插值计算位置
            selectedObject.position.lerpVectors(
                new THREE.Vector3(prevKeyframe.position.x, prevKeyframe.position.y, prevKeyframe.position.z),
                new THREE.Vector3(nextKeyframe.position.x, nextKeyframe.position.y, nextKeyframe.position.z),
                easedT
            );
            
            // 插值计算旋转（使用四元数避免万向锁问题）
            const prevQuat = new THREE.Quaternion().setFromEuler(
                new THREE.Euler(
                    THREE.MathUtils.degToRad(prevKeyframe.rotation.x),
                    THREE.MathUtils.degToRad(prevKeyframe.rotation.y),
                    THREE.MathUtils.degToRad(prevKeyframe.rotation.z)
                )
            );
            
            const nextQuat = new THREE.Quaternion().setFromEuler(
                new THREE.Euler(
                    THREE.MathUtils.degToRad(nextKeyframe.rotation.x),
                    THREE.MathUtils.degToRad(nextKeyframe.rotation.y),
                    THREE.MathUtils.degToRad(nextKeyframe.rotation.z)
                )
            );
            
            // 使用四元数球面线性插值
            const currentQuat = new THREE.Quaternion();
            currentQuat.slerpQuaternions(prevQuat, nextQuat, easedT);
            
            // 将四元数转换回欧拉角
            const euler = new THREE.Euler().setFromQuaternion(currentQuat);
            selectedObject.rotation.set(euler.x, euler.y, euler.z);
            
            // 插值计算缩放
            selectedObject.scale.lerpVectors(
                new THREE.Vector3(prevKeyframe.scale.x, prevKeyframe.scale.y, prevKeyframe.scale.z),
                new THREE.Vector3(nextKeyframe.scale.x, nextKeyframe.scale.y, nextKeyframe.scale.z),
                easedT
            );
            
            // 更新属性面板
            updatePropertiesPanel();
        }
        
        // 缓入函数
        function easeIn(t) {
            return t * t;
        }
        
        // 缓出函数
        function easeOut(t) {
            return t * (2 - t);
        }
        
        // 缓入缓出函数
        function easeInOut(t) {
            return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
        }
        
        // 添加立方体
        function addCube() {
            const geometry = new THREE.BoxGeometry(1, 1, 1);
            const material = new THREE.MeshStandardMaterial({ 
                color: 0xff6b6b,
                metalness: 0.5,
                roughness: 0.5
            });
            const cube = new THREE.Mesh(geometry, material);
            cube.name = "立方体";
            cube.castShadow = true;
            cube.receiveShadow = true;
            scene.add(cube);
            objects.push(cube);
            updateObjectsList();
            selectObject(cube);
        }
        
        // 添加球体
        function addSphere() {
            const geometry = new THREE.SphereGeometry(0.5, 32, 32);
            const material = new THREE.MeshStandardMaterial({ 
                color: 0x4ecdc4,
                metalness: 0.5,
                roughness: 0.5
            });
            const sphere = new THREE.Mesh(geometry, material);
            sphere.name = "球体";
            sphere.castShadow = true;
            sphere.receiveShadow = true;
            scene.add(sphere);
            objects.push(sphere);
            updateObjectsList();
            selectObject(sphere);
        }
        
        // 添加圆锥体
        function addCone() {
            const geometry = new THREE.ConeGeometry(0.5, 1, 32);
            const material = new THREE.MeshStandardMaterial({ 
                color: 0xffe66d,
                metalness: 0.5,
                roughness: 0.5
            });
            const cone = new THREE.Mesh(geometry, material);
            cone.name = "圆锥体";
            cone.castShadow = true;
            cone.receiveShadow = true;
            scene.add(cone);
            objects.push(cone);
            updateObjectsList();
            selectObject(cone);
        }
        
        // 添加圆柱体
        function addCylinder() {
            const geometry = new THREE.CylinderGeometry(0.5, 0.5, 1, 32);
            const material = new THREE.MeshStandardMaterial({ 
                color: 0x6a0572,
                metalness: 0.5,
                roughness: 0.5
            });
            const cylinder = new THREE.Mesh(geometry, material);
            cylinder.name = "圆柱体";
            cylinder.castShadow = true;
            cylinder.receiveShadow = true;
            scene.add(cylinder);
            objects.push(cylinder);
            updateObjectsList();
            selectObject(cylinder);
        }
        
        // 添加平面
        function addPlane() {
            const geometry = new THREE.PlaneGeometry(5, 5);
            const material = new THREE.MeshStandardMaterial({ 
                color: 0x7c7c7c,
                metalness: 0.3,
                roughness: 0.8,
                side: THREE.DoubleSide
            });
            const plane = new THREE.Mesh(geometry, material);
            plane.name = "平面";
            plane.rotation.x = Math.PI / 2;
            plane.receiveShadow = true;
            scene.add(plane);
            objects.push(plane);
            updateObjectsList();
            selectObject(plane);
        }
        
        // 添加相机
        function addCamera() {
            const newCamera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
            newCamera.name = "相机 " + (cameras.length + 1);
            newCamera.position.set(3, 3, 3);
            newCamera.lookAt(0, 0, 0);
            scene.add(newCamera);
            cameras.push(newCamera);
            objects.push(newCamera);
            updateObjectsList();
            selectObject(newCamera);
        }
        
        // 更新对象列表
        function updateObjectsList() {
            const objectsList = document.getElementById('objectsList');
            objectsList.innerHTML = '';
            
            objects.forEach(obj => {
                const li = document.createElement('li');
                li.className = 'object-item';
                if (obj === selectedObject) {
                    li.classList.add('selected');
                }
                
                li.innerHTML = `
                    <span>${obj.name}</span>
                    <div class="object-visibility">👁️</div>
                `;
                
                li.addEventListener('click', () => {
                    selectObject(obj);
                });
                
                objectsList.appendChild(li);
            });
        }
        
        // 选择对象
        function selectObject(object) {
            selectedObject = object;
            keyframes = object.userData.keyframes || [];
            updateObjectsList();
            updatePropertiesPanel();
            updateTimeline();
            
            // 如果是相机，切换到该相机
            if (object.isCamera) {
                camera = object;
                controls.object = camera;
                controls.update();
            }
        }
        
        // 更新属性面板
        function updatePropertiesPanel() {
            if (!selectedObject) return;
            
            // 更新变换属性
            document.getElementById('positionX').value = selectedObject.position.x;
            document.getElementById('positionY').value = selectedObject.position.y;
            document.getElementById('positionZ').value = selectedObject.position.z;
            
            document.getElementById('rotationX').value = THREE.MathUtils.radToDeg(selectedObject.rotation.x);
            document.getElementById('rotationY').value = THREE.MathUtils.radToDeg(selectedObject.rotation.y);
            document.getElementById('rotationZ').value = THREE.MathUtils.radToDeg(selectedObject.rotation.z);
            
            document.getElementById('scaleX').value = selectedObject.scale.x;
            document.getElementById('scaleY').value = selectedObject.scale.y;
            document.getElementById('scaleZ').value = selectedObject.scale.z;
            
            // 更新材质属性（如果对象有材质）
            if (selectedObject.material) {
                document.getElementById('materialColor').value = '#' + selectedObject.material.color.getHexString();
                document.getElementById('materialColorPicker').value = '#' + selectedObject.material.color.getHexString();
                document.getElementById('metalness').value = selectedObject.material.metalness;
                document.getElementById('roughness').value = selectedObject.material.roughness;
                document.getElementById('opacity').value = selectedObject.material.opacity;
            }
        }
        
        // 添加关键帧
        function addKeyframe() {
            if (!selectedObject) return;
            
            // 确保对象有关键帧数组
            if (!selectedObject.userData.keyframes) {
                selectedObject.userData.keyframes = [];
            }
            
            // 创建关键帧数据
            const keyframe = {
                time: currentTime,
                position: {
                    x: selectedObject.position.x,
                    y: selectedObject.position.y,
                    z: selectedObject.position.z
                },
                rotation: {
                    x: THREE.MathUtils.radToDeg(selectedObject.rotation.x),
                    y: THREE.MathUtils.radToDeg(selectedObject.rotation.y),
                    z: THREE.MathUtils.radToDeg(selectedObject.rotation.z)
                },
                scale: {
                    x: selectedObject.scale.x,
                    y: selectedObject.scale.y,
                    z: selectedObject.scale.z
                }
            };
            
            // 添加到关键帧数组
            selectedObject.userData.keyframes.push(keyframe);
            
            // 按时间排序
            selectedObject.userData.keyframes.sort((a, b) => a.time - b.time);
            
            // 更新关键帧数组引用
            keyframes = selectedObject.userData.keyframes;
            
            // 更新时间轴
            updateTimeline();
        }
        
        // 删除关键帧
        function removeKeyframe() {
            if (!selectedObject || !selectedKeyframe) return;
            
            // 从关键帧数组中移除选中的关键帧
            const index = keyframes.indexOf(selectedKeyframe);
            if (index !== -1) {
                keyframes.splice(index, 1);
            }
            
            selectedKeyframe = null;
            
            // 更新时间轴
            updateTimeline();
        }
        
        // 更新时间轴显示
        function updateTimeline() {
            const track = document.getElementById('timelineTrack');
            const curve = document.getElementById('animationCurve');
            
            // 清除现有内容
            track.querySelectorAll('.keyframe, .keyframe-line').forEach(el => el.remove());
            curve.innerHTML = '';
            
            // 如果没有关键帧，直接返回
            if (keyframes.length === 0) return;
            
            // 添加关键帧之间的连线
            for (let i = 0; i < keyframes.length - 1; i++) {
                const line = document.createElement('div');
                line.className = 'keyframe-line';
                line.style.left = (keyframes[i].time / animationDuration * 100) + '%';
                line.style.width = ((keyframes[i+1].time - keyframes[i].time) / animationDuration * 100) + '%';
                track.appendChild(line);
            }
            
            // 添加关键帧标记
            keyframes.forEach(kf => {
                const keyframeEl = document.createElement('div');
                keyframeEl.className = 'keyframe';
                if (kf === selectedKeyframe) {
                    keyframeEl.classList.add('selected');
                }
                keyframeEl.style.left = (kf.time / animationDuration * 100) + '%';
                
                keyframeEl.addEventListener('click', () => {
                    selectKeyframe(kf);
                });
                
                track.appendChild(keyframeEl);
            });
            
            // 添加动画曲线预览
            drawAnimationCurve();
        }
        
        // 绘制动画曲线
        function drawAnimationCurve() {
            const curve = document.getElementById('animationCurve');
            curve.innerHTML = '';
            
            // 简单示例：绘制位置X的动画曲线
            if (keyframes.length < 2) return;
            
            const points = 50;
            const width = curve.offsetWidth;
            const height = curve.offsetHeight;
            
            // 找到X位置的最小和最大值
            let minX = Infinity;
            let maxX = -Infinity;
            
            keyframes.forEach(kf => {
                if (kf.position.x < minX) minX = kf.position.x;
                if (kf.position.x > maxX) maxX = kf.position.x;
            });
            
            // 确保有足够的范围
            if (maxX - minX < 1) {
                minX -= 0.5;
                maxX += 0.5;
            }
            
            // 创建曲线点
            for (let i = 0; i <= points; i++) {
                const t = i / points * animationDuration;
                
                // 找到当前时间所在的关键帧区间
                let prevKeyframe = null;
                let nextKeyframe = null;
                
                for (let j = 0; j < keyframes.length; j++) {
                    if (keyframes[j].time <= t) {
                        prevKeyframe = keyframes[j];
                    } else {
                        nextKeyframe = keyframes[j];
                        break;
                    }
                }
                
                // 如果不在任何区间内，跳过
                if (!prevKeyframe || !nextKeyframe) continue;
                
                // 计算时间比例 (0到1之间)
                const timeRatio = (t - prevKeyframe.time) / (nextKeyframe.time - prevKeyframe.time);
                
                // 应用插值函数
                let easedT = timeRatio;
                switch (interpolationType) {
                    case 'easeIn':
                        easedT = easeIn(timeRatio);
                        break;
                    case 'easeOut':
                        easedT = easeOut(timeRatio);
                        break;
                    case 'easeInOut':
                        easedT = easeInOut(timeRatio);
                        break;
                    default:
                        // 线性插值，不需要修改
                        break;
                }
                
                // 计算插值位置
                const x = prevKeyframe.position.x + (nextKeyframe.position.x - prevKeyframe.position.x) * easedT;
                
                // 归一化到0-1范围
                const normalizedX = (x - minX) / (maxX - minX);
                
                // 创建曲线点
                const point = document.createElement('div');
                point.className = 'curve-point';
                point.style.left = (t / animationDuration * 100) + '%';
                point.style.top = (100 - normalizedX * 100) + '%';
                
                curve.appendChild(point);
            }
        }
        
        // 选择关键帧
        function selectKeyframe(keyframe) {
            selectedKeyframe = keyframe;
            
            // 跳转到关键帧时间
            currentTime = keyframe.time;
            updatePlayhead();
            
            // 更新对象属性到关键帧状态
            if (selectedObject) {
                selectedObject.position.set(
                    keyframe.position.x,
                    keyframe.position.y,
                    keyframe.position.z
                );
                
                selectedObject.rotation.set(
                    THREE.MathUtils.degToRad(keyframe.rotation.x),
                    THREE.MathUtils.degToRad(keyframe.rotation.y),
                    THREE.MathUtils.degToRad(keyframe.rotation.z)
                );
                
                selectedObject.scale.set(
                    keyframe.scale.x,
                    keyframe.scale.y,
                    keyframe.scale.z
                );
                
                updatePropertiesPanel();
            }
            
            // 更新时间轴显示
            updateTimeline();
            
            // 更新关键帧属性面板
            updateKeyframeProperties();
        }
        
        // 更新关键帧属性面板
        function updateKeyframeProperties() {
            const propertiesPanel = document.getElementById('keyframeProperties');
            
            if (!selectedKeyframe) {
                propertiesPanel.innerHTML = '<p>选择关键帧以编辑属性</p>';
                return;
            }
            
            propertiesPanel.innerHTML = `
                <div class="property">
                    <label>时间</label>
                    <input type="number" id="keyframeTime" value="${selectedKeyframe.time}" step="0.1" min="0" max="${animationDuration}">
                </div>
                <div class="property">
                    <label>位置 X</label>
                    <input type="number" id="keyframePosX" value="${selectedKeyframe.position.x}" step="0.1">
                </div>
                <div class="property">
                    <label>位置 Y</label>
                    <input type="number" id="keyframePosY" value="${selectedKeyframe.position.y}" step="0.1">
                </div>
                <div class="property">
                    <label>位置 Z</label>
                    <input type="number" id="keyframePosZ" value="${selectedKeyframe.position.z}" step="0.1">
                </div>
                <button class="tool-btn" id="updateKeyframe">更新关键帧</button>
            `;
            
            // 添加更新事件
            document.getElementById('updateKeyframe').addEventListener('click', updateSelectedKeyframe);
        }
        
        // 更新选中的关键帧
        function updateSelectedKeyframe() {
            if (!selectedKeyframe) return;
            
            // 更新关键帧属性
            selectedKeyframe.time = parseFloat(document.getElementById('keyframeTime').value);
            selectedKeyframe.position.x = parseFloat(document.getElementById('keyframePosX').value);
            selectedKeyframe.position.y = parseFloat(document.getElementById('keyframePosY').value);
            selectedKeyframe.position.z = parseFloat(document.getElementById('keyframePosZ').value);
            
            // 按时间重新排序
            keyframes.sort((a, b) => a.time - b.time);
            
            // 更新时间轴
            updateTimeline();
        }
        
        // 初始化UI事件
        function initUI() {
            // 添加模型按钮
            document.getElementById('addCube').addEventListener('click', addCube);
            document.getElementById('addSphere').addEventListener('click', addSphere);
            document.getElementById('addCone').addEventListener('click', addCone);
            document.getElementById('addCylinder').addEventListener('click', addCylinder);
            document.getElementById('addPlane').addEventListener('click', addPlane);
            document.getElementById('addCamera').addEventListener('click', addCamera);
            
            // 工具选择
            const toolButtons = document.querySelectorAll('.tool-btn');
            toolButtons.forEach(button => {
                button.addEventListener('click', function() {
                    if (this.id === 'selectTool' || this.id === 'moveTool' || 
                        this.id === 'rotateTool' || this.id === 'scaleTool') {
                        toolButtons.forEach(btn => btn.classList.remove('active'));
                        this.classList.add('active');
                    }
                });
            });
            
            // 属性标签切换
            document.querySelectorAll('.property-tab').forEach(tab => {
                tab.addEventListener('click', function() {
                    document.querySelectorAll('.property-tab').forEach(t => t.classList.remove('active'));
                    this.classList.add('active');
                    
                    document.querySelectorAll('.property-content').forEach(content => {
                        content.style.display = 'none';
                    });
                    
                    document.getElementById(this.dataset.tab + 'Tab').style.display = 'block';
                });
            });
            
            // 播放控制
            document.getElementById('playBtn').addEventListener('click', function() {
                isPlaying = true;
                clock.start();
            });
            
            document.getElementById('pauseBtn').addEventListener('click', function() {
                isPlaying = false;
            });
            
            document.getElementById('stopBtn').addEventListener('click', function() {
                isPlaying = false;
                currentTime = 0;
                updatePlayhead();
                updateAnimations();
            });
            
            // 时间轴滑块
            document.getElementById('timelineSlider').addEventListener('input', function() {
                currentTime = (this.value / 100) * animationDuration;
                updatePlayhead();
                updateAnimations();
            });
            
            // 当前时间输入
            document.getElementById('currentTimeInput').addEventListener('change', function() {
                currentTime = parseFloat(this.value);
                if (currentTime < 0) currentTime = 0;
                if (currentTime > animationDuration) currentTime = animationDuration;
                updatePlayhead();
                updateAnimations();
            });
            
            // 关键帧导航
            document.getElementById('prevKeyframe').addEventListener('click', function() {
                if (keyframes.length === 0) return;
                
                let prevKeyframe = null;
                for (let i = keyframes.length - 1; i >= 0; i--) {
                    if (keyframes[i].time < currentTime) {
                        prevKeyframe = keyframes[i];
                        break;
                    }
                }
                
                if (prevKeyframe) {
                    selectKeyframe(prevKeyframe);
                }
            });
            
            document.getElementById('nextKeyframe').addEventListener('click', function() {
                if (keyframes.length === 0) return;
                
                let nextKeyframe = null;
                for (let i = 0; i < keyframes.length; i++) {
                    if (keyframes[i].time > currentTime) {
                        nextKeyframe = keyframes[i];
                        break;
                    }
                }
                
                if (nextKeyframe) {
                    selectKeyframe(nextKeyframe);
                }
            });
            
            // 关键帧操作
            document.getElementById('addKeyframe').addEventListener('click', addKeyframe);
            document.getElementById('removeKeyframe').addEventListener('click', removeKeyframe);
            
            // 预览模式
            document.getElementById('previewBtn').addEventListener('click', function() {
                isPreviewMode = !isPreviewMode;
                this.textContent = isPreviewMode ? '编辑模式' : '预览模式';
                document.getElementById('modeIndicator').textContent = isPreviewMode ? '预览模式' : '编辑模式';
                
                controls.enabled = !isPreviewMode;
            });
            
            // 导出模态框
            document.getElementById('exportBtn').addEventListener('click', function() {
                document.getElementById('exportModal').style.display = 'flex';
            });
            
            document.getElementById('closeExportModal').addEventListener('click', function() {
                document.getElementById('exportModal').style.display = 'none';
            });
            
            // 背景设置模态框
            document.getElementById('changeBg').addEventListener('click', function() {
                document.getElementById('backgroundModal').style.display = 'flex';
            });
            
            document.getElementById('closeBackgroundModal').addEventListener('click', function() {
                const color = document.getElementById('backgroundColor').value;
                scene.background = new THREE.Color(color);
                document.getElementById('backgroundModal').style.display = 'none';
            });
            
            // 属性变化
            document.getElementById('positionX').addEventListener('change', updateObjectProperties);
            document.getElementById('positionY').addEventListener('change', updateObjectProperties);
            document.getElementById('positionZ').addEventListener('change', updateObjectProperties);
            document.getElementById('rotationX').addEventListener('change', updateObjectProperties);
            document.getElementById('rotationY').addEventListener('change', updateObjectProperties);
            document.getElementById('rotationZ').addEventListener('change', updateObjectProperties);
            document.getElementById('scaleX').addEventListener('change', updateObjectProperties);
            document.getElementById('scaleY').addEventListener('change', updateObjectProperties);
            document.getElementById('scaleZ').addEventListener('change', updateObjectProperties);
            
            document.getElementById('materialColor').addEventListener('change', updateObjectProperties);
            document.getElementById('materialColorPicker').addEventListener('change', function() {
                document.getElementById('materialColor').value = this.value;
                updateObjectProperties();
            });
            document.getElementById('metalness').addEventListener('input', updateObjectProperties);
            document.getElementById('roughness').addEventListener('input', updateObjectProperties);
            document.getElementById('opacity').addEventListener('input', updateObjectProperties);
            
            // 动画时长变化
            document.getElementById('animationDuration').addEventListener('change', function() {
                animationDuration = parseFloat(this.value);
                document.getElementById('timeIndicator').textContent = currentTime.toFixed(1) + 's / ' + animationDuration.toFixed(1) + 's';
                initTimeline();
                updateTimeline();
            });
            
            // 插值方式变化
            document.getElementById('interpolationType').addEventListener('change', function() {
                interpolationType = this.value;
                updateTimeline();
            });
        }
        
        // 更新对象属性
        function updateObjectProperties() {
            if (!selectedObject) return;
            
            // 更新变换属性
            selectedObject.position.x = parseFloat(document.getElementById('positionX').value);
            selectedObject.position.y = parseFloat(document.getElementById('positionY').value);
            selectedObject.position.z = parseFloat(document.getElementById('positionZ').value);
            
            selectedObject.rotation.x = THREE.MathUtils.degToRad(parseFloat(document.getElementById('rotationX').value));
            selectedObject.rotation.y = THREE.MathUtils.degToRad(parseFloat(document.getElementById('rotationY').value));
            selectedObject.rotation.z = THREE.MathUtils.degToRad(parseFloat(document.getElementById('rotationZ').value));
            
            selectedObject.scale.x = parseFloat(document.getElementById('scaleX').value);
            selectedObject.scale.y = parseFloat(document.getElementById('scaleY').value);
            selectedObject.scale.z = parseFloat(document.getElementById('scaleZ').value);
            
            // 更新材质属性（如果对象有材质）
            if (selectedObject.material) {
                selectedObject.material.color.set(document.getElementById('materialColor').value);
                selectedObject.material.metalness = parseFloat(document.getElementById('metalness').value);
                selectedObject.material.roughness = parseFloat(document.getElementById('roughness').value);
                selectedObject.material.opacity = parseFloat(document.getElementById('opacity').value);
                selectedObject.material.transparent = selectedObject.material.opacity < 1;
                selectedObject.material.needsUpdate = true;
            }
        }
        
        // 初始化应用
        window.addEventListener('load', function() {
            init();
            initUI();
            
            // 添加初始对象
            addCube();
        });
    </script>
</body>
</html>